#include "i2c_soft.h"
#include "stm32f4xx.h"
#include "board.h"

#include <rtdevice.h>

#ifdef RT_USING_I2C_BITOPS

#define I2C1_PORT        GPIOB
#define I2C1_PIN_CLK     GPIO_PIN_6
#define I2C1_PIN_SDA     GPIO_PIN_7

struct rt_i2c_bus_device i2c1_bus;

void i2c1_set_pin_clk(void *data, rt_int32_t state)
{
    if (state)
    {
        HAL_GPIO_WritePin(I2C1_PORT, I2C1_PIN_CLK, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(I2C1_PORT, I2C1_PIN_CLK, GPIO_PIN_RESET);
    }

}

rt_int32_t i2c1_get_pinState_clk(void *data)
{
    return HAL_GPIO_ReadPin(I2C1_PORT, I2C1_PIN_CLK);
}

void i2c1_set_pin_sda(void *data, rt_int32_t state)
{
    if (state)
    {
        HAL_GPIO_WritePin(I2C1_PORT, I2C1_PIN_SDA, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(I2C1_PORT, I2C1_PIN_SDA, GPIO_PIN_RESET);
    }
}

rt_int32_t i2c1_get_pinState_sda(void *data)
{
    return HAL_GPIO_ReadPin(I2C1_PORT, I2C1_PIN_SDA);
}

void udelay(rt_uint32_t us)
{
    volatile rt_uint32_t i;
    for (; us > 0; us--)
    {
        i = 50;
        while(i--);
    }
}
static struct rt_i2c_bit_ops i2c1_bit_ops =
{
    NULL,
    i2c1_set_pin_sda,
    i2c1_set_pin_clk,
    i2c1_get_pinState_sda,
    i2c1_get_pinState_clk,
    udelay,
    5,
    100,
};


void HAL_I2C_Soft_MspInit(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin     = I2C1_PIN_CLK | I2C1_PIN_SDA;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_HIGH;
    HAL_GPIO_Init(I2C1_PORT, &GPIO_InitStruct);
    HAL_GPIO_WritePin(I2C1_PORT, I2C1_PIN_SDA|I2C1_PIN_CLK, GPIO_PIN_SET);
}

int rt_hw_i2c_init(void)
{
    i2c1_bus.priv = &i2c1_bit_ops;

    /* if i2c start and receive NACK, retry until receive ACK */
    i2c1_bus.retries = 20;

    HAL_I2C_Soft_MspInit();

    rt_i2c_bit_add_bus(&i2c1_bus, "i2c1");

    return 0;
}

INIT_BOARD_EXPORT(rt_hw_i2c_init);

#endif  // RT_USING_I2C_BITOPS

